package com.boot.controller;

import com.boot.entity.*;
import com.boot.repository.*;
import com.boot.vo.BaseMessage;
import com.boot.vo.Course;
import com.boot.vo.MessageHandler;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;

import javax.transaction.Transactional;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

@RestController
@CrossOrigin(origins = "*")

@RequestMapping("/selCourse")
public class SelectCourseController {
    @Resource
    SelectCourseRepository selectCourseRepository;
    @Resource
    CourseInfoRepository courseInfoRepository;
    @Resource
    StuInfoRepository stuInfoRepository;
    @Resource
    TeaInfoRepository teaInfoRepository;
    @Resource
    TimeAndPlaceRepository timeAndPlaceRepository;
    @Resource
    CourseApplicationRepository courseApplicationRepository;
    @Resource
    ClassroomRepository classroomRepository;

    @Autowired
    private TermRepository termRepository;

    @Autowired
    private CourseOpenRepository courseOpenRepository;

    // 学生选课第一轮
    @RequestMapping("round1Sel")
    @ResponseBody
    public BaseMessage<?> selcourse1(String stunum, String courseid) {
        SelectCourse selectCourse = new SelectCourse();
        selectCourse.setStunum(stunum);
        selectCourse.setCourseid(Integer.parseInt(courseid));
        Integer termId = judgeTermId();
        CourseOpen courseOpen = courseOpenRepository.findByTermId(termId);
        if (!courseOpen.getOpenOne()) {
            return MessageHandler.createFailedVo("选课未开启！");
        }
        LocalDateTime startTimeOne = courseOpen.getStartTimeOne();
        LocalDateTime endTimeOne = courseOpen.getEndTimeOne();
        LocalDateTime now = LocalDateTime.now();
        if (now.isBefore(startTimeOne) || now.isAfter(endTimeOne)) {
            return MessageHandler.createFailedVo("不在选课时间！");
        }

        String s = check(selectCourse);
        if (s.startsWith("0") || s.startsWith("2")) {
            selectCourseRepository.save(selectCourse);
            CourseInfo courseInfo = courseInfoRepository.findByCourseSerialNumber(selectCourse.getCourseid());
            courseInfo.setCourseEnrollment(courseInfo.getCourseEnrollment() + 1);
            courseInfoRepository.save(courseInfo);
            return MessageHandler.createSuccessVo(s.substring(1, s.length()));
        } else
            return MessageHandler.createFailedVo(s.substring(1, s.length()) + "选课失败");
    }

    //管理员第一轮选课结束踢人
    @Transactional
    @RequestMapping("round1kick")
    public void kick() {
        List<SelectCourse> selectCourseAll = selectCourseRepository.findAll();
        Set<Integer> courseSet = selectCourseAll.stream().filter(x -> x.getCourseid() != null).map(SelectCourse::getCourseid).collect(Collectors.toSet());
        for (Integer i : courseSet) {
            CourseInfo courseInfo = courseInfoRepository.findByCourseSerialNumber(i);
            if (courseInfo.getCourseEnrollment() > courseInfo.getCourseCapacity()) {
                List<SelectCourse> selectCourseById = selectCourseRepository.findSelectCourseByCourseid(i);
                selectCourseById.sort(Comparator.comparing(SelectCourse::getStunum));//按照学号从小到大排序；
                List<SelectCourse> newSelCourse = selectCourseById.subList(0, courseInfo.getCourseCapacity()); //截取成符合课程人数
                selectCourseRepository.deleteAllByCourseid(i);  //全删了再全部加上
                selectCourseRepository.flush(); //如果不flush就会报错
                selectCourseRepository.saveAll(newSelCourse);
                courseInfo.setCourseEnrollment(courseInfo.getCourseCapacity()); //更新人数
                courseInfoRepository.save(courseInfo);
            }
        }

    }

//第二轮选课

    @RequestMapping("round2Sel")
    @ResponseBody
    public BaseMessage<?> round2Sel(String stunum, String courseid) {
        SelectCourse selectCourse = new SelectCourse();
        selectCourse.setStunum(stunum);
        selectCourse.setCourseid(Integer.parseInt(courseid));

        Integer termId = judgeTermId();
        CourseOpen courseOpen = courseOpenRepository.findByTermId(termId);
        if (!courseOpen.getOpenTwo()) {
            return MessageHandler.createFailedVo("选课未开启！");
        }
        LocalDateTime startTimeOne = courseOpen.getStartTimeTwo();
        LocalDateTime endTimeOne = courseOpen.getEndTimeTwo();
        LocalDateTime now = LocalDateTime.now();

        if (now.isBefore(startTimeOne) || now.isAfter(endTimeOne)) {
            return MessageHandler.createFailedVo("不在选课时间！");
        }

        String s = check(selectCourse);
        if (s.startsWith("0")) {
            selectCourseRepository.save(selectCourse);
            CourseInfo courseInfo = courseInfoRepository.findByCourseSerialNumber(selectCourse.getCourseid());
            courseInfo.setCourseEnrollment(courseInfo.getCourseEnrollment() + 1);
            courseInfoRepository.save(courseInfo);
            return MessageHandler.createSuccessVo(s.substring(1, s.length()));
        } else
            return MessageHandler.createFailedVo(s.substring(1, s.length()) + "，选课失败");
    }


    // 查看所有课程的选课名单,返回一个stuInfo类
    @GetMapping("stuList")
    public BaseMessage<?> selectCourseList(@RequestParam Integer courseId) {
        Boolean b1 = courseInfoRepository.existsByCourseSerialNumber(courseId);
        if (b1 == false) return MessageHandler.createFailedVo("课程信息不存在");
        List<SelectCourse> selectCourseList = selectCourseRepository.findSelectCourseByCourseid(courseId);
        List<StuInfo> stuInfos = new ArrayList<>();
        for (SelectCourse s : selectCourseList) {
            StuInfo stuInfo = stuInfoRepository.findByStudentNumber(s.getStunum());
            stuInfos.add(stuInfo);
        }
        return MessageHandler.createSuccessVo(stuInfos, "");
    }


    //学生查看已选课程(courseInfo---zch)
    @GetMapping("allCompletedList")
    public BaseMessage<?> allCompletedList(@RequestParam String stunum) {
        Boolean b1 = stuInfoRepository.existsByStudentNumber(stunum);
        if (b1 == false) return MessageHandler.createFailedVo("学生信息不存在");
        List<SelectCourse> selectCourseList = selectCourseRepository.findSelectCourseByStunum(stunum);
        List<CourseInfo> courseInfoList = new ArrayList<>();
        for (SelectCourse s : selectCourseList) {
            CourseInfo courseInfo = courseInfoRepository.findByCourseSerialNumber(s.getCourseid());
            courseInfoList.add(courseInfo);
        }
        return MessageHandler.createSuccessVo(courseInfoList, "");
    }


    //学生查看已选课程(课程表形式---sc )  termId 值没有传过来 这个是当前学期还是什么
    @GetMapping("completedList")
    public BaseMessage<?> completedList(String stunum) {
        Integer termId = judgeTermId();
        Boolean b1 = stuInfoRepository.existsByStudentNumber(stunum);
        if (b1 == false) return MessageHandler.createFailedVo("学生信息不存在");
        List<SelectCourse> selectCourseList = selectCourseRepository.findSelectCourseByStunum(stunum);
        List<Course> courseList = new ArrayList<>();
        for (SelectCourse s : selectCourseList) {
            CourseInfo courseInfo = courseInfoRepository.findByCourseSerialNumber(s.getCourseid());
            List<TimeAndPlace> taps = timeAndPlaceRepository.findAllByCourseSerialNumber(s.getCourseid());
            if (courseInfo.getTermId() == termId) {
                for (TimeAndPlace tap : taps) {
                    Course course = courseInfoAndTAPToCourse(courseInfo, tap);
                    courseList.add(course);
                }
            }
        }
        return MessageHandler.createSuccessVo(courseList, "");
    }

    //教师查看所授课程
    @GetMapping("teaCourseList")
    public BaseMessage<?> teaCourseList(@RequestParam String worknum) {
        Boolean b = courseInfoRepository.existsByWorkNumber(worknum);
        if (b == false)
            return MessageHandler.createFailedVo("没有该教师");
        List<CourseInfo> courseInfoList = courseInfoRepository.findAllByWorkNumber(worknum);
        return MessageHandler.createSuccessVo(courseInfoList, "");
    }
/*
    //教师查看所授课程
    @GetMapping("teaCourseList")
    public BaseMessage<?> teaCourseList(@RequestParam String worknum, @RequestParam Integer termid) {
        Boolean b = courseInfoRepository.existsByWorkNumberAndTermId(worknum, termid);
        if (b == false)
            return MessageHandler.createFailedVo("该学期您没有执教的课程");
        List<CourseInfo> courseInfoList = courseInfoRepository.findAllByWorkNumberAndTermId(worknum, termid);
        return MessageHandler.createSuccessVo(courseInfoList, "");
    }
*/


    //教师查看所教课程的选课名单
    @GetMapping("teachingList")
    public BaseMessage<?> teachingList(@RequestParam Integer courseId) {
        List<SelectCourse> selectCourseList = selectCourseRepository.findSelectCourseByCourseid(courseId);
        List<StuInfo> stuInfos = new ArrayList<>();
        for (SelectCourse selectCourse : selectCourseList) {
            StuInfo stuInfo = stuInfoRepository.findByStudentNumber(selectCourse.getStunum());
            stuInfos.add(stuInfo);
        }
        return MessageHandler.createSuccessVo(stuInfos, "");
    }


    //退选
    @Transactional
    @RequestMapping("dropCourse")
    public BaseMessage<?> dropCourse(Integer cid, String stunum) {
        Boolean b = selectCourseRepository.existsByStunumAndCourseid(stunum, cid);
        if (b == false) return MessageHandler.createFailedVo("不退不退，你也妹选这个课啊");
        selectCourseRepository.deleteSelectCoursesByCourseidAndStunum(cid, stunum);
        CourseInfo courseInfo = courseInfoRepository.findByCourseSerialNumber(cid);
        courseInfo.setCourseEnrollment(courseInfo.getCourseEnrollment() - 1);
        courseInfoRepository.save(courseInfo);
        return MessageHandler.createSuccessVo("退选");
    }


    //选课申请（学生）
    @PostMapping("applyCourse")
    @ResponseBody
    public BaseMessage<?> applyCourse(@RequestBody CourseApplication courseApplication) {
        Boolean b1 = stuInfoRepository.existsByStudentNumber(courseApplication.getStunum());
        if (b1 == false) return MessageHandler.createFailedVo("该学号不存在");
        Boolean b2 = courseInfoRepository.existsByCourseSerialNumber(courseApplication.getCourseid());
        if (b2 == false) return MessageHandler.createFailedVo("该课程序列号不存在");
        courseApplicationRepository.save(courseApplication);
        return MessageHandler.createSuccessVo("提交成功");
    }

    //管理员查看所有申请
    @GetMapping("applyCourseList")
    public BaseMessage<?> applyCourseList() {
        List<CourseApplication> courseApplications = courseApplicationRepository.findAll();
        return MessageHandler.createSuccessVo(courseApplications, "");
    }

    //管理员管理申请（需要前端返回CourseApplication类里的id给我,Integer类型; 还有通不过通过：true/false）
    @Transactional
    @RequestMapping("applicationMgt")
    @ResponseBody
    public BaseMessage<?> applicationMgt(@RequestParam Integer id, @RequestParam Boolean b) {
        CourseApplication courseApplication = courseApplicationRepository.getById(id);
        courseApplicationRepository.deleteById(courseApplication.getId());
        CourseInfo courseInfo = courseInfoRepository.findByCourseSerialNumber(courseApplication.getCourseid());
        List<TimeAndPlace> timeAndPlaces = timeAndPlaceRepository.findAllByCourseSerialNumber(courseApplication.getCourseid());
        List<Classroom> classroomList = new ArrayList<>();
        for (TimeAndPlace timeAndPlace : timeAndPlaces) {
            Classroom classroom = classroomRepository.findByClassroomName(timeAndPlace.getClassroom());
            //教室人满了
            if (courseInfo.getCourseCapacity() >= classroom.getCapacity())
                return MessageHandler.createFailedVo(classroom.getClassroomName() + "的教室容量已达上限");
            classroomList.add(classroom);
        }
        //通过申请
        if (b == true) {
            courseInfo.setCourseCapacity(courseInfo.getCourseCapacity() + 1);
            courseInfo.setCourseEnrollment(courseInfo.getCourseEnrollment() + 1);
            courseInfoRepository.save(courseInfo);
            SelectCourse selectCourse = new SelectCourse();
            selectCourse.setCourseid(courseInfo.getCourseSerialNumber());
            selectCourse.setStunum(courseApplication.getStunum());
            selectCourseRepository.save(selectCourse);
            return MessageHandler.createSuccessVo("选课申请通过");
        }
        return MessageHandler.createFailedVo("选课理由不充分");
    }


    //扩容、缩容
    @PostMapping("changeCapacity")
    @ResponseBody
    public BaseMessage<?> changeCapacity(@RequestParam Integer courseId, @RequestParam Integer newCapacity) {
        CourseInfo courseInfo = courseInfoRepository.findByCourseSerialNumber(courseId);
        if (courseInfo.getCourseEnrollment() > newCapacity)
            return MessageHandler.createFailedVo("课程容量应不少于已选课⼈数");
        List<TimeAndPlace> timeAndPlaces = timeAndPlaceRepository.findAllByCourseSerialNumber(courseId);
        for (TimeAndPlace timeAndPlace : timeAndPlaces) {
            Classroom classroom = classroomRepository.findByClassroomName(timeAndPlace.getClassroom());
            if (newCapacity > classroom.getCapacity())
                return MessageHandler.createFailedVo("课程容量不超过该课程对应教室的容量");
        }

        courseInfo.setCourseCapacity(newCapacity);
        courseInfoRepository.save(courseInfo);
        return MessageHandler.createSuccessVo("容量修改成功");
    }


    //学生：根据学年学期、上课时间(星期几、第几节）、上课地点找课。第几节课就是一个数字，比如说周一的2-5是高数，我查找周一的第4节课就能显示高数，查第1节就啥也没有
    @GetMapping("/stu/findByTermAndTimeAndPlace")
    public BaseMessage<?> stuFindByTermAndTimeAndPlace(String stunum, Integer termid, Integer weekday, Integer jieshu, String classroom) {
        StuInfo stu = stuInfoRepository.findByStudentNumber(stunum);
        List<TimeAndPlace> taps = timeAndPlaceRepository.findAllByWeekdayAndClassroom(weekday, classroom);
        CourseInfo courseInfo = new CourseInfo();
        for (TimeAndPlace tap : taps) {
            //1、找所有星期几、节数、教室符合的
            if (jieshu <= tap.getEnd() && jieshu >= tap.getStart()) {
                courseInfo = courseInfoRepository.findByCourseSerialNumber(tap.getCourseSerialNumber());
                //2、再判断是不是这个学期的
                if (courseInfo.getTermId() == termid)
                    //3、再判断可选专业
                    if (Selectable(courseInfo.getKxzy(), stu.getMajorId()) == true)
                        return MessageHandler.createSuccessVo(courseInfo, "查找成功");
            }
        }
        return MessageHandler.createFailedVo("该学期该时间地点没有课程");
    }


    //根据课程编号模糊搜索
    @GetMapping("stu/findByCourseNum")
    public BaseMessage<?> stufFindByCourseNum(String stunum, Integer cnum) {
        StuInfo stu = stuInfoRepository.findByStudentNumber(stunum);
        List<CourseInfo> courseInfoList = courseInfoRepository.findAllByCourseNumberLike(cnum);
        if (courseInfoList.size() == 0 || null == courseInfoList) {
            return MessageHandler.createFailedVo("该课程编号不存在");
        }

        List<CourseInfo> result = new ArrayList<>();
        for (CourseInfo c : courseInfoList) {
            if (Selectable(c.getKxzy(), stu.getMajorId()) == true) {
                result.add(c);
            }
        }

        return MessageHandler.createSuccessVo(result, "");
    }

    //根据课程老师名字模糊搜索
    @GetMapping("stu/findByTeaName")
    public BaseMessage<?> stuFindByCourseNum(String stunum, String teaname) {
        StuInfo stu = stuInfoRepository.findByStudentNumber(stunum);
        //名字模糊搜索工号
        List<TeaInfo> teaInfos = teaInfoRepository.findAllByNameLike(teaname);
        if (teaInfos.isEmpty()) {
            return MessageHandler.createFailedVo("该教师不存在");
        }

        List<CourseInfo> tempList = new ArrayList<>();
        for (TeaInfo teaInfo : teaInfos) {
            tempList.addAll(courseInfoRepository.findAllByWorkNumber(teaInfo.getWorkNumber()));

        }
        List<CourseInfo> result = new ArrayList<>();
        for (CourseInfo c : tempList) {
            if (Selectable(c.getKxzy(), stu.getMajorId()) == true) {
                result.add(c);
            }

        }

        return MessageHandler.createSuccessVo(result, "");
    }

    //根据课程名字模糊搜索
    @GetMapping("stu/findByCourseName")
    public BaseMessage<?> stuFindByCourseName(String stunum, String cname) {
        StuInfo stu = stuInfoRepository.findByStudentNumber(stunum);
        List<CourseInfo> courseInfoList = courseInfoRepository.findAllByCourseNameLike(cname);
        if (courseInfoList.size() == 0 || null == courseInfoList) {
            return MessageHandler.createFailedVo("该课程名字不存在");
        }

        List<CourseInfo> result = new ArrayList<>();
        for (CourseInfo c : courseInfoList) {
            if (Selectable(c.getKxzy(), stu.getMajorId()) == true) {
                result.add(c);
            }
        }

        return MessageHandler.createSuccessVo(result, "");
    }


    // 验证能不能选课
    public String check(SelectCourse selectCourse) {
        //1、存在性
        Boolean b1 = courseInfoRepository.existsByCourseSerialNumber(selectCourse.getCourseid());
        if (b1 == false)
            return "1该课程不存在";
        Boolean b2 = stuInfoRepository.existsByStudentNumber(selectCourse.getStunum());
        if (b2 == false)
            return "1该学生不存在";
        //2、合法性
        CourseInfo courseInfo = courseInfoRepository.findByCourseSerialNumber(selectCourse.getCourseid());
        StuInfo stuInfo = stuInfoRepository.findByStudentNumber(selectCourse.getStunum());
        List<SelectCourse> selectCourseList = selectCourseRepository.findSelectCourseByStunum(selectCourse.getStunum());  //已经选过的课
        //if (courseInfo.getStatus() == 0)
        //   return "1该学期未开课";  不用status了
        Boolean selectable = Selectable(courseInfo.getKxzy(), stuInfo.getMajorId());
        if (selectable == false)
            return "1专业限制不可选课";
        for (SelectCourse s : selectCourseList) {
            CourseInfo temp = courseInfoRepository.findByCourseSerialNumber(s.getCourseid());
            if (temp.getCourseName() == courseInfo.getCourseName() && temp.getCourseNumber() == courseInfo.getCourseNumber())
                return "1不可以重复选课";
        }
        if (courseInfo.getCourseEnrollment() >= courseInfo.getCourseCapacity())
            return "2人数已达最大限额";
        return "0可以选课";
    }


    // 验证专业限制
    public Boolean Selectable(String kxzy, Integer majorId) {
        if (kxzy.equals("0")) {
            return true;
        } else if (kxzy.startsWith("1")) {
            String temp = kxzy.substring(2, kxzy.length());
            String[] arr = temp.split("@");
            for (String s1 : arr) {
                if (Integer.parseInt(s1) == majorId) {
                    return true;
                }

            }

        } else if (kxzy.startsWith("2")) {
            String temp2 = kxzy.substring(2, kxzy.length());
            if (Integer.parseInt(temp2) == majorId) {
                return true;
            }

        }
        return false;
    }

    //courseInfo和tap到course
    public Course courseInfoAndTAPToCourse(CourseInfo courseInfo, TimeAndPlace timeAndPlace) {
        Course c = new Course();
        c.setCourseSerialNumber(courseInfo.getCourseSerialNumber());
        c.setCourseNumber(courseInfo.getCourseNumber());
        c.setCourseName(courseInfo.getCourseName());
        c.setSchoolId(courseInfo.getSchoolId());
        c.setCourseCredit(courseInfo.getCourseCredit());
        c.setCoursePeriod(courseInfo.getCoursePeriod());
        c.setWorkNumber(courseInfo.getWorkNumber());
        c.setCourseDesc(courseInfo.getCourseDesc());
        c.setCourseEnrollment(courseInfo.getCourseEnrollment());
        c.setMajorId(courseInfo.getMajorId());
        c.setCourseCapacity(courseInfo.getCourseCapacity());
        c.setKxzy(courseInfo.getKxzy());
        c.setTermId(courseInfo.getTermId());
        c.setStatus(0);
        c.setFlag(true);   //审核状态默认为true,选课状态默认为0
        c.setStart(timeAndPlace.getStart());
        c.setEnd(timeAndPlace.getEnd());
        c.setBuilding(timeAndPlace.getBuilding());
        c.setClassroom(timeAndPlace.getClassroom());
        c.setWeekday(timeAndPlace.getWeekday());
        return c;
    }

    public Integer judgeTermId() {
        Calendar cal = Calendar.getInstance();
        int month = cal.get(Calendar.MONTH);
        Integer year = cal.get(Calendar.YEAR);
        Integer term;   //1/2学期
        if (month >= 2 && month <= 6)
            term = 2;
        else if (month >= 9 || month == 1)
            term = 1;
        else
            term = 3;
        Term term1 = termRepository.findByYearAndTerm(year, term);
        return term1.getTermid();
    }

}
